package com.yingdong.sceneserver;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.yingdong.gateserver.innter.service.ConfigService;
import com.yingdong.sceneserver.net.HttpServerInboundHandler;
import com.yingdong.sceneserver.net.SceneServerHandlerNetty4;
import com.yingdong.sceneserver.net.frager.SceneServerPacketDefragerNetty4;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;

public class SceneServer {
	static Log logger = LogFactory.getLog(SceneServer.class);

	private SceneServer() {

	}

	private static SceneServer instance;

	public static SceneServer getInstance() {
		if (instance == null)
			instance = new SceneServer();
		return instance;
	}

	public void reconnectGateserver() {

		EventLoopGroup workerGroup = new NioEventLoopGroup();

		try {
			Bootstrap b = new Bootstrap(); // (1)
			b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
			b.group(workerGroup); // (2)
			b.channel(NioSocketChannel.class); // (3)
			b.option(ChannelOption.SO_KEEPALIVE, true); // (4)
			b.option(ChannelOption.TCP_NODELAY, Boolean.TRUE);
			b.option(ChannelOption.SO_REUSEADDR, Boolean.TRUE);
			b.handler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch) throws Exception {
					ch.pipeline().addLast(new SceneServerHandlerNetty4());
				}
			});

			// Start the client.
			ChannelFuture f = b.connect(ConfigService.getPropertyString("gate.server.ip"), ConfigService.getPropertyInt("scene.server.port")).sync(); // (5)

			// Wait until the connection is closed.
			// f.channel().closeFuture().sync();
		} catch (Exception e) {
			logger.error("", e);
		} finally {

		}

	}

	public void run() {
		ConfigService.init();
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		try {
			Bootstrap b = new Bootstrap(); // (1)
			b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
			b.group(workerGroup); // (2)
			b.channel(NioSocketChannel.class); // (3)
			b.option(ChannelOption.SO_KEEPALIVE, true); // (4)
			b.option(ChannelOption.TCP_NODELAY, Boolean.TRUE);
			b.option(ChannelOption.SO_REUSEADDR, Boolean.TRUE);
			b.handler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch) throws Exception {
					ch.pipeline().addLast(new SceneServerPacketDefragerNetty4(), new SceneServerHandlerNetty4());
				}
			});

			// Start the client.
			b.connect(ConfigService.getPropertyString("gate.server.ip"), ConfigService.getPropertyInt("scene.server.port")).sync(); // (5)
			logger.info("连接网关服务器成功");

		} catch (Exception e) {
			logger.info("连接网关服务器失败");
		}
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		workerGroup = new NioEventLoopGroup();
		try {
			ServerBootstrap b = new ServerBootstrap();
			b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch) throws Exception {
					// server端发送的是httpResponse，所以要使用HttpResponseEncoder进行编码
					ch.pipeline().addLast(new HttpResponseEncoder());
					// server端接收到的是httpRequest，所以要使用HttpRequestDecoder进行解码
					ch.pipeline().addLast(new HttpRequestDecoder());
					ch.pipeline().addLast(new HttpServerInboundHandler());
				}
			}).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);

			ChannelFuture f = b.bind(ConfigService.getPropertyInt("scene.server.http.port")).sync();

		} catch (Exception e) {
			logger.info("",e);
		}
		try {
			GlobalInitManager.init();
		} catch (Exception e) {
			logger.error("", e);
		}

	}

}
